#!/usr/bin/env node -r ./livescript-transform-implicit-async/register

require! {
  \fs-extra : \fs
  \csv-parse : \parse
}

toc = require('markdown-toc')

require! <[
  dayjs
  nodemailer
  path
  xlsx
]>


{Remarkable} = require \remarkable
quarterOfYear = require \dayjs/plugin/quarterOfYear
advancedFormat = require \dayjs/plugin/advancedFormat

render = (str)~>
  r = new Remarkable(
    {
      html:true
    }
  )
  _render = r.renderer.render
  r.renderer.rules.heading_open = (tokens, idx)->
    tok = tokens[idx]
    tokContent = tokens[idx + 1]
    if tokContent.slug
      heading = '<h' + tok.hLevel + ' id="' + tokContent.slug + '">'
      return heading
    return '<h' + tok.hLevel + '>'

  out = r.use(toc.plugin()).render(str)
  return _render.call(r.renderer, out.tokens, r.options)

dayjs.extend(quarterOfYear)
dayjs.extend(advancedFormat)

ROOT = path.join(__dirname, "项目")
TODAY = dayjs().format('YYYY-MM-DD')

set-default = (d, key, val)~>
  if not (key of d)
    d[key] = val
  return d[key]

class Task
  (@name, @list)->
    @todo = {}
    @done = {}
    @expire = {}

  push:([目录, 交付时间, 任务, 负责人,备注])->
    suffix = 任务.split(".")

    is-file = false
    if suffix.length > 1
      suffix = suffix.pop()
      if /^[a-zA-Z]+$/.test(suffix)
        is-file = true

        for duration in ["年",'季','月']
          if 任务.indexOf("$"+duration) + 1
            now = dayjs()
            switch duration
              when \月
                任务 = now.add(-1,'month').format('YYYY-MM')
              when \季
                任务 = now.add(-1,'quarter').format('YYYY-[q]Q')
              when \年
                任务 = now.add(-1,'year').format('YYYY')
            任务=任务+"."+suffix
            break

        filepath = path.join(ROOT, @name, 目录, 任务)
        done = await fs.exists filepath

    if not is-file
      done = 任务.startsWith("#")
      if done
        任务 = 任务.slice(1)

    if done
      li = @done
    else
      if 交付时间 < TODAY
        li = @expire
      else
        li = @todo
    set-default(
      set-default(li,负责人 or '',{})
      交付时间 or ''
      []
    ).push(
      [
        "#{目录}/"+任务.trim()
        备注
      ]
    )
    # console.log @
    # console.log 任务
    # if not 交付时间
    #   li = set-default(@todo,'',[])
    # console.log @name , 负责人+"@"+@mail, 目录, 交付时间, 任务, 备注


parse_csv = (task, csv)->
  n = 0
  prev = [void,void,void]
  todo = []

  new Promise(
    (resolve)~>
      parse(
        csv
        * skip_empty_lines:true
          trim:true
      ).on(
        \readable
        ->
          while 1
            line = @read!
            if line
              line = line.slice(0,5)
              if n
                for i,pos in prev
                  line[pos] = line[pos] or prev[pos]
                [目录, 交付时间, 任务, 负责人, 备注] = line
                if 目录
                  prev[0] = 目录
                if not 任务
                  continue
                if 交付时间 == '-'
                  continue
                if 交付时间 == '#'
                  prev[1] = "#"
                  continue
                todo.push task.push line
                prev := line.slice(0,3)
              else
                task.mail = line[3].split(" ",1)[0]
              ++n
            else
              break
      ).on(
        \end
        ->
          await Promise.all(todo)
          resolve()
      )
  )

parse_xlsx = (task, data)->
  for k,v of data.Sheets
    await parse_csv task, xlsx.utils.sheet_to_csv(v)

sort_dict = (d)~>
  li = []
  for k,v of d
    li.push [k,v]
  li.sort (a,b)~>
    if a>b
      return 1
    return -1
  return li

do ~>
  task-li = []
  for i in await fs.readdir(ROOT)
    i0 = i.charAt(0)
    if '._'.indexOf(i0) + 1
      continue
    dirpath = path.join(ROOT, i)
    for j in await fs.readdir(dirpath)
      if j.endsWith('清单.xlsx') and not j.startsWith("~")
        console.log j
        filepath = path.join dirpath, j
        task = new Task(i, j.slice(0,-7))
        task-li.push task
        await parse_xlsx task, xlsx.readFile(filepath)

  cn = [
    \超时
    \计划
    \完成
  ]

  md= []
  for name, pos in [ \expire, \todo , \done  ]
    md.push "\n# " + cn[pos] + "\n"
    for i in task-li
      md.push "\n## " + task.name + " · " + task.list
      for [user , li] in sort_dict(i[name])
        count = 0
        for k,v of li
          count += v.length
        md.push "\n### "+(user or '未分配')+" - "+count+"\n"
        for [date,line] in sort_dict(i[name][user])
          md.push "* "+(date or '未排期')
          for [txt,mark] in line
            md.push "  0. "+txt
            if mark
              md.push "\n     "+mark

  md = md.join("\n")
  # console.log md

  html = render(toc(md).content+"\n"+md)
  sender = 'task@mail.xvc.com'

  transporter = nodemailer.createTransport({
    host: "smtpdm.aliyun.com"
    port: 465
    secureConnection: true
    auth: {
      user:  sender
      pass: 'iMA5jkFndkX0'
    }
  })

  to = \zsp@xvc.com

  transporter.sendMail(
    {
      from:sender
      subject:"任务清单 "+TODAY
      to
      replyTo:"team@xvc.com"
      html
    }

    (err,info)~>
      if err
        console.error err
      console.log TODAY, info
  )
